﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Windows.UI.Text;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using XamlInspector.Foundation;
using XamlInspector.Model;

namespace XamlInspector.Presentation.Controls
{
    public class VisualTreeItem : ViewModelBase
    {
        private readonly MergeableObservableCollection<VisualTreeItem> _visibleItems;
        private readonly Func<XamlElement, VisualTreeItem> _getVisualTreeItem;
        private bool _isExpanded;

        public VisualTreeItem(MergeableObservableCollection<VisualTreeItem> visibleItems, Func<XamlElement, VisualTreeItem> getVisualTreeItem, XamlElement element)
        {
            _visibleItems = visibleItems;
            _getVisualTreeItem = getVisualTreeItem;

            Element = element;
        }

        public XamlElement Element { get; private set; }

        public ImageSource Icon
        {
            get
            {
                return EmbeddedResourceProvider.GetImage("window.png");
            }
        }

        public VisualTreeItem Parent
        {
            get
            {
                if (Element.Parent != null)
                {
                    return _getVisualTreeItem(Element.Parent);
                }
                return null;
            }
        }

        public IEnumerable<VisualTreeItem> Children
        {
            get { return Element.Children.Select(e => _getVisualTreeItem(e)); }
        }

        public ImageSource Preview
        {
            get
            {
                var bitmap = new RenderTargetBitmap();
                bitmap.RenderAsync((UIElement)Element.Element);
                return bitmap;
            }
        }

        public Thickness Margin
        {
            get { return new Thickness(Element.NestingLevel * 12, 0, 0, 0); }
        }

        public FontWeight FontWeight
        {
            get
            {
                if (Element.Element is Control)
                {
                    return FontWeights.SemiBold;
                }
                return FontWeights.Normal;
            }
        }

        public bool IsExpanded
        {
            get { return _isExpanded; }
            set
            {
                if (ChangeAndNotify(value, ref _isExpanded))
                {
                    if (_isExpanded)
                    {
                        ExpandSubTree();
                    }
                    else
                    {
                        CollapseSubTree();
                    }
                }
            }
        }

        private void ExpandSubTree()
        {
            var insertPos = _visibleItems.IndexOf(this);
            foreach (var visualTreeItem in Children)
            {
                _visibleItems.Insert(insertPos + 1, visualTreeItem);
            }
        }

        private void CollapseSubTree()
        {
            foreach (var visualTreeItem in Children)
            {
                _visibleItems.Remove(visualTreeItem);
                visualTreeItem.CollapseSubTree();
            }
        }

        public bool HasChildren
        {
            get { return Element.Children.Any(); }
        }

        public void ExpandTree()
        {
            var path = new List<VisualTreeItem>();

            var element = this;
            while (element != null)
            {
                path.Add(element);
                element = element.Parent;
            }
            path.Reverse();

            foreach (var visualTreeItem in path)
            {
                visualTreeItem.IsExpanded = true;
            }
        }

        public override string ToString()
        {
            return Element.Text;
        }
    }
}
